package com.gopay.solution.domain.bo.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.gopay.common.constants.solution.ProfitDtlStatus;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.solution.ProfitReq;
import com.gopay.common.domain.solution.ProfitRes;
import com.gopay.solution.domain.po.SolutionRuleDtl;
import com.gopay.solution.domain.po.SsTransProfitDtl;
import com.gopay.solution.domain.vo.Event;
import com.gopay.solution.domain.vo.Result;

/**
 * 返润方案规则执行器
 * @SsTransProfitSoluRuleExecutor.java
 * @author wanggang
 * @2014-7-10 下午2:54:10  www.gopay.com.cn Inc.All rights reserved.
 */
@Service(value="ssTransProfitSoluRuleExecutor")
public class SsTransProfitSoluRuleExecutor extends AbstractSolutionRuleExecutor {

    @Override
    public Result execute(List<SolutionRuleDtl> rules, Event event) {
        Result result = new Result();
        result.setSolved(false);
        result.setFailedReason("");
        result.setDetail(null);

        if (null == rules || rules.isEmpty()) {
            result.setFailedReason("查询不到返润方案记录");
            return result;
        }

        Serializable input = event.getDetail();

        ProfitReq req = (ProfitReq) input;
        String profitMonth = req.getProfitMonth();
        String payChann = req.getPayChannel();
        IntTxnCd intTxnCd = req.getIntTxnCd();
        String acctType = req.getAcctType();
        BigDecimal amount = req.getAmount();
        boolean isResetData = req.isResetData();
        
        for (SolutionRuleDtl rule : rules) {
            SsTransProfitDtl dtl = (SsTransProfitDtl) rule;
            if (StringUtils.equals(dtl.getAcctType(), acctType) 
                    && StringUtils.equals(dtl.getPayChannel(), payChann) 
                    && StringUtils.equals(dtl.getGopayIntTxnCd(), intTxnCd.value)
                    && StringUtils.equals(dtl.getDtlStatus(), ProfitDtlStatus._00.value)
                    ) {
                
                if(dtl.getTransAuth() != 1){
                    result.setFailedReason("此账户未开通返润方案");
                    return result;
                }
                ProfitRes res = new ProfitRes();
                //非重置数据，校验日期
                if(!isResetData){
                    String startDate = dtl.getTransStartDate();
                    String endDate = dtl.getTransEndDate();
                    Calendar begin = Calendar.getInstance();
                    begin.set(Calendar.YEAR, Integer.parseInt(startDate.substring(0, 4)));
                    begin.set(Calendar.MONTH, Integer.parseInt(startDate.substring(4)));
                    int year,month; 
                    try{
                        year = Integer.parseInt(profitMonth.substring(0, 4));
                        month = Integer.parseInt(profitMonth.substring(4));
                    }catch(Exception e){
                        result.setFailedReason("此请求参数profitMonth有误，格式为yyyyMM");
                        return result;
                    }
                    Calendar profit = Calendar.getInstance();
                    profit.set(Calendar.YEAR, year);
                    profit.set(Calendar.MONTH, month);
                    if(StringUtils.isBlank(endDate)){//未设置截止日期
                        //只校验开始日期
                        if(profit.before(begin)){
                            result.setFailedReason("返点月份小于方案开始日期");
                            return result;
                        }
                    }else{
                        //校验开始日期和结束日期
                        Calendar end = Calendar.getInstance();
                        end.set(Calendar.YEAR, Integer.parseInt(endDate.substring(0, 4)));
                        end.set(Calendar.MONTH, Integer.parseInt(endDate.substring(4)));
                        if(profit.before(begin)){
                            result.setFailedReason("返点月份小于方案开始日期");
                            return result;
                        }
                        if(profit.after(end)){
                            result.setFailedReason("返点月份大于方案结束日期");
                            return result;
                        }
                    }
                    res.setBeginDate(startDate);
                    res.setEndDate(endDate);
                }
                if(dtl.getIsEnable() != 1){
                    result.setFailedReason("此支付渠道未开通返润方案");
                    return result;
                }
                if(dtl.getCalExp() == null){
                    result.setFailedReason("查询不到此支付渠道返润方案计算公式");
                    return result;
                }        
                res = calProfit(res, amount, dtl.getCalExp());
                result.setSolved(true);
                result.setFailedReason("");
                result.setDetail(res);
                
                if (null != result.getDetail()) {
                    result.setSolved(true);
                }
                return result;
            }            
        }
        result.setFailedReason("查询不到此交易返润方案记录");
        return result;        
    }
    
    /**
     * 计算方法，完善返回信息
     * 补充返点费率profitRatio返还手续费金额profitAmt返润方案profitSolution
     * @param amount
     * @param calExp
     * @return
     */
    private ProfitRes calProfit(ProfitRes res, BigDecimal amount,String calExp) {
   
        String[] ranges = StringUtils.split(calExp, '#');
        for (String range : ranges) {
            String[] param = StringUtils.split(range, '-');
            BigDecimal start = new BigDecimal(param[0]).multiply(new BigDecimal("10000"));// 起始值 万元换成元
            String endStr = param[1];
            BigDecimal end = StringUtils.equals("+", endStr) ? new BigDecimal(String.valueOf(Long.MAX_VALUE))
                    : new BigDecimal(endStr).multiply(new BigDecimal("10000"));// 结束值 万元换成元         
            if (amount.compareTo(start) >= 0 && amount.compareTo(end) < 0) {
                BigDecimal rate = new BigDecimal(param[2]);
                res.setProfitRatio(rate);
                res.setProfitSolution(param[0] + "^" + endStr + "," + rate + "%");
                res.setProfitAmt(amount.multiply(rate.multiply(new BigDecimal("0.01"))).setScale(2, BigDecimal.ROUND_HALF_UP));
                return res;
            }
        }
        logger.error("返润计算错误，amount: " + amount + ", calExp: " + calExp);
        return null;
    }
}
